package com.bbcare.comm;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.io.IOUtils;

import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.SuccessCallback;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

public class HttpUtil {
    private static Log log = LogFactory.getLog(HttpUtil.class);

    @Resource
    private RestTemplate restTemplate;


    public static String postDataText(String url, Map<String, Object> msg) throws Exception {
        String result = null;
        PostMethod method = null;
        try {
            assertMsgNotNull(msg.toString());

            long begin = System.currentTimeMillis();
            HttpClient httpClient = new HttpClient();
            httpClient.getParams().setContentCharset("UTF-8");
            httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");

            // 增加超时时间限制
            iniTimeOut(httpClient);

            int mapSize = msg.size();
            if (0 == mapSize) {
                throw new Exception("待发送的报文为空，请核实！");
            }
            NameValuePair[] nvpArr = new NameValuePair[mapSize];
            Iterator<String> iter = msg.keySet().iterator();
            String key = "";
            int i = 0;
            while (iter.hasNext()) {
                key = iter.next();
                nvpArr[i] = new NameValuePair(key, "" + msg.get(key));
                i++;
            }

            method = new PostMethod(url);
            method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
            method.setRequestBody(nvpArr);
            log.warn("准备发送目标URL为:" + method.getURI());
            log.warn("入参：" + msg.toString());
            httpClient.executeMethod(method);

            InputStream in = method.getResponseBodyAsStream();
            result = IOUtils.toString(in, "utf-8");
            IOUtils.closeQuietly(in);

            int statu_code = method.getStatusLine().getStatusCode();
            assertResultSuccess(statu_code);

            log.warn("响应报文为：" + result);
            log.warn("发送请求,完成,耗时:" + (System.currentTimeMillis() - begin) + "毫秒");
        } catch (Exception e) {
            log.error("对端接口发送失败！", e);
            //TODO 暂时注释掉处理
            //throw e;
            //港大代码会报错，把异常吃掉
            System.out.println("对端接口发送失败！LLQLL");
            return null;
        } finally {
            if (method != null) {
                method.releaseConnection();
            }
        }
        return result;
    }




    public static String postData(String url, String msg) {

        Thread t = new Thread(new Runnable(){
            @Override
            public void run(){
                // run方法具体重写
                String result = null;
                PostMethod method = null;
                try {
                    assertMsgNotNull(msg);

                    long begin = System.currentTimeMillis();
                    log.info("发送请求,开始:==>>" +url+","+ msg);
                    HttpClient httpClient = new HttpClient();
                    // 设置代理服务器地址和端口
                    if (org.apache.commons.lang.StringUtils.isNotBlank(PropertiesUtils.getProperty("proxy")))  {
                        httpClient.getHostConfiguration().setProxy("192.168.61.103",8089);
                    }

                    // 增加超时时间限制
                    iniTimeOut(httpClient);

                    method = new PostMethod(url);
                    StringRequestEntity entity = new StringRequestEntity(msg, "application/json", "utf-8");
                    method.setRequestEntity(entity);
                    httpClient.executeMethod(method);

                    InputStream in = method.getResponseBodyAsStream();
                    result = IOUtils.toString(in, "utf-8");
                    IOUtils.closeQuietly(in);

                    int statu_code = method.getStatusLine().getStatusCode();

                    log.info("发送请求,完成,耗时:" + (System.currentTimeMillis() - begin)+",响应报文为：" + result);

                    assertResultSuccess(statu_code);
                } catch (Exception e) {
                    log.error("对端接口发送失败！", e);
                } finally {
                    if (method != null) {
                        method.releaseConnection();
                    }
                }
            }

        });
        t.start();
        return "finish postHttpStringDataAsyn post";
    }


    /*public static String postData(String url, String msg)  {
        try {
            postHttpStringDataAsyn(url,msg);
        }catch (Exception ex ){
            log.error(ex.getMessage());
        }


        return "发送完成";
    }*/

    /**
     * 增加超时时间限制
     *
     * @author DemonLee
     * @date 2017.5.29
     *
     * @param httpClient
     */
    private static void iniTimeOut(HttpClient httpClient) {
        int conAndSoTimeOut = 30000;// default 30 seconds
        String timeOut = PropertiesUtils.getProperty("HTTPConTimeOut");
        if (null != timeOut && !"".equals(timeOut)) {
            conAndSoTimeOut = Integer.parseInt(timeOut);
        }
        log.debug("超时设定为：" + conAndSoTimeOut);
        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(conAndSoTimeOut);
        httpClient.getHttpConnectionManager().getParams().setSoTimeout(conAndSoTimeOut);
        httpClient.getParams().setSoTimeout(conAndSoTimeOut);
    }

    private static void assertMsgNotNull(String msg) throws Exception {
        if (StringUtils.isEmpty(msg)) {
            log.warn("待发送的报文为空，请核实！");
            throw new Exception("待发送的报文为空，请核实！");
        }
    }

    private static void assertResultSuccess(int statu_code) throws Exception {
        if (statu_code == 200 || statu_code == 204) {
        } else {
            log.error("调用对端接口响应错误,响应码为" + statu_code);
            throw new Exception("调用对端接口响应错误,响应码为" + statu_code);
        }
    }


    public static String postHttpStringDataAsyn(String URL, String postStr) throws IOException {
        // 发送异步post , 非阻塞, 发送完无需等待结果返回
        System.out.println("异步发送开始");
        AsyncRestTemplate client = new AsyncRestTemplate();
        client.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        ListenableFuture<ResponseEntity<String>> listenableFuture = client.postForEntity(URL, new HttpEntity<Object>(postStr), String.class);
        listenableFuture.addCallback(new SuccessCallback<ResponseEntity<String>>() {
            @Override
            public void onSuccess(ResponseEntity<String> result) {
                System.out.println("("+result.getStatusCode()+ ":"+result.getStatusCode().getReasonPhrase()+ "):"+result.getBody());

            }
        }, new FailureCallback() {
            @Override
            public void onFailure(Throwable ex) {
                ex.printStackTrace();
                System.out.println(ex);
            }
        });
        return "finish postHttpStringDataAsyn post";

    }



}
